package rexsee.network;

import java.util.List;

import rexsee.core.browser.Browser;
import rexsee.core.browser.clazz.JavascriptInterface;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.DhcpInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.Status;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.provider.Settings;
import android.provider.Settings.System;
import android.text.TextUtils;

public class RexseeWiFi implements JavascriptInterface {

	public static final String INTERFACE_NAME = "WiFi";
	@Override
	public String getInterfaceName() {
		return mBrowser.application.resources.prefix + INTERFACE_NAME;
	}
	@Override
	public JavascriptInterface getInheritInterface(Browser childBrowser) {
		return this;
	}
	@Override
	public JavascriptInterface getNewInterface(Browser childBrowser) {
		return new RexseeWiFi(childBrowser);
	}

	// Constants used for different security types
	private static final String SECURITY_NONE = "OPEN";
	private static final String SECURITY_WEP = "WEP";
	private static final String SECURITY_PSK = "WPA/WPA2 PSK";
	private static final String SECURITY_EAP = "EAP";

	private static final String EXCEPTION_NOT_ENABLED = "WiFi is not enabled yet, please call enable().";

	private static final String EVENT_ONSTATECHANGED = "onWiFiStateChanged";
	private static final String EVENT_ONNETWORKCHANGED = "onWiFiNetworkChanged";
	private static final String EVENT_ONNETWORKIDSCHANGED = "onWiFiNetworkIdsChanged";
	private static final String EVENT_ONRSSICHANGED = "onWiFiRssiChanged";
	private static final String EVENT_ONSCANFINISHED = "onWiFiScanFinished";
	private static final String EVENT_ONSUPPLICANTCONNECTIONCHANGED = "onWiFiSupplicantConnectionChanged";
	private static final String EVENT_ONSUPPLICANTSTATECHANGED = "onWiFiSupplicantStateChanged";

	private final BroadcastReceiver EVENT_ONSTATECHANGED_Receiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String state = _getWiFiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, -1));
			String previousState = _getWiFiState(intent.getIntExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, -1));
			mBrowser.eventList.run(EVENT_ONSTATECHANGED, new String[]{state, previousState});
		}
	};
	private final BroadcastReceiver EVENT_ONNETWORKIDSCHANGED_Receiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			mBrowser.eventList.run(EVENT_ONNETWORKIDSCHANGED);
		}
	};
	private final BroadcastReceiver EVENT_ONNETWORKCHANGED_Receiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			mBrowser.eventList.run(EVENT_ONNETWORKCHANGED);
		}
	};
	private final BroadcastReceiver EVENT_ONRSSICHANGED_Receiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			int rssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, 0);
			mBrowser.eventList.run(EVENT_ONRSSICHANGED, new String[]{String.valueOf(rssi)});
		}
	};
	private final BroadcastReceiver EVENT_ONSCANFINISHED_Receiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			mBrowser.eventList.run(EVENT_ONSCANFINISHED);
		}
	};
	private final BroadcastReceiver EVENT_ONSUPPLICANTCONNECTIONCHANGED_Receiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			boolean connected = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false);
			mBrowser.eventList.run(EVENT_ONSUPPLICANTCONNECTIONCHANGED, new String[]{String.valueOf(connected)});
		}
	};
	private final BroadcastReceiver EVENT_ONSUPPLICANTSTATECHANGED_Receiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String state = _getSupplicantState((SupplicantState) intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE));
			mBrowser.eventList.run(EVENT_ONSUPPLICANTSTATECHANGED, new String[]{state});
		}
	};

	private void error(String msg) {
		mBrowser.exception(getInterfaceName(), "WiFi Error: " + msg);
	}

	private static String _removeDoubleQuotes(String string) {
		int length = string.length();
		if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
			return string.substring(1, length - 1);
		} else {
			return string;
		}
	}
	private static String _convertToQuotedString(String string) {
		return "\"" + string + "\"";
	}
	private static String _getWiFiState(int state) {
		switch (state) {
			case WifiManager.WIFI_STATE_DISABLED :
				return "disabled";
			case WifiManager.WIFI_STATE_DISABLING :
				return "disabling";
			case WifiManager.WIFI_STATE_ENABLED :
				return "enabled";
			case WifiManager.WIFI_STATE_ENABLING :
				return "enabling";
			default :
				return "unknown";
		}
	}
	private static String _getSupplicantState(SupplicantState state) {
		if (state.equals(SupplicantState.ASSOCIATED)) return "associated";
		else if (state.equals(SupplicantState.ASSOCIATING)) return "associating";
		else if (state.equals(SupplicantState.COMPLETED)) return "completed";
		else if (state.equals(SupplicantState.DISCONNECTED)) return "disconnected";
		else if (state.equals(SupplicantState.DORMANT)) return "dormant";
		else if (state.equals(SupplicantState.FOUR_WAY_HANDSHAKE)) return "four_way_handshake";
		else if (state.equals(SupplicantState.GROUP_HANDSHAKE)) return "group_handshake";
		else if (state.equals(SupplicantState.INACTIVE)) return "inactive";
		else if (state.equals(SupplicantState.SCANNING)) return "scanning";
		else if (state.equals(SupplicantState.UNINITIALIZED)) return "uninitialized";
		else return "invalid";

	}
	private static String _getSecurity(WifiConfiguration config) {
		if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { return SECURITY_PSK; }
		if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
				config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { return SECURITY_EAP; }
		return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
	}
	private static String _getSecurity(ScanResult result) {
		if (result.capabilities.contains("WEP")) {
			return SECURITY_WEP;
		} else if (result.capabilities.contains("PSK")) {
			return SECURITY_PSK;
		} else if (result.capabilities.contains("EAP")) { return SECURITY_EAP; }
		return SECURITY_NONE;
	}
	private static boolean _hasPassword(WifiConfiguration wifiConfig) {
		return !TextUtils.isEmpty(wifiConfig.preSharedKey)
				|| !TextUtils.isEmpty(wifiConfig.wepKeys[0])
				|| !TextUtils.isEmpty(wifiConfig.wepKeys[1])
				|| !TextUtils.isEmpty(wifiConfig.wepKeys[2])
				|| !TextUtils.isEmpty(wifiConfig.wepKeys[3]);
	}
	private static String _getStatus(int status) {
		switch (status) {
			case WifiConfiguration.Status.CURRENT :
				return "current";
			case WifiConfiguration.Status.DISABLED :
				return "disabled";
			case WifiConfiguration.Status.ENABLED :
				return "enabled";
			default :
				return "unknown";
		}

	}
	private static boolean _match(ScanResult result, WifiConfiguration config) {
		if (result == null || config == null) return false;
		if (config.BSSID != null && !config.BSSID.equals(result.BSSID)) return false;
		if (!config.SSID.equals(result.SSID) && !config.SSID.equals(_convertToQuotedString(result.SSID))) return false;
		if (_getSecurity(result) != _getSecurity(config)) return false;
		return true;
	}
	private static int _getRememberedId(ScanResult result, List<WifiConfiguration> configs) {
		if (result == null || configs == null) return -1;
		for (int i = 0; i < configs.size(); i++) {
			WifiConfiguration config = configs.get(i);
			if (_match(result, config)) return config.networkId;
		}
		return -1;
	}
	private static String _getScannedBSSID(List<ScanResult> results, WifiConfiguration config) {
		if (results == null || config == null) return "";
		for (int i = 0; i < results.size(); i++) {
			ScanResult result = results.get(i);
			if (_match(result, config)) return result.BSSID;
		}
		return "";
	}
	private static String _getConfiguredNetwork(List<ScanResult> results, WifiConfiguration config) {
		String rtn = "";
		rtn += "\"networkId\":" + config.networkId;
		rtn += ",\"BSSID\":" + ((config.BSSID == null) ? null : "\"" + config.BSSID + "\"");
		rtn += ",\"SSID\":\"" + _removeDoubleQuotes(config.SSID) + "\"";
		rtn += ",\"priority\":" + config.priority + "";
		rtn += ",\"status\":\"" + _getStatus(config.status) + "\"";
		rtn += ",\"security\":\"" + _getSecurity(config) + "\"";
		rtn += ",\"hasPassword\":" + ((_hasPassword(config)) ? "true" : "false");
		rtn += ",\"scannedBSSID\":\"" + _getScannedBSSID(results, config) + "\"";
		return "{" + rtn + "}";
	}
	private static String _getScanResult(ScanResult result, List<WifiConfiguration> configs) {
		String rtn = "";
		rtn += "\"BSSID\":\"" + result.BSSID + "\"";
		rtn += ",\"SSID\":\"" + result.SSID + "\"";
		rtn += ",\"frequency\":" + result.frequency;
		rtn += ",\"level\":" + result.level;
		rtn += ",\"security\":\"" + _getSecurity(result) + "\"";
		rtn += ",\"rememberedId\":" + String.valueOf(_getRememberedId(result, configs));
		return "{" + rtn + "}";
	}
	private static String _getIpAddress(int addr) {
		return String.format("%d.%d.%d.%d", addr & 0xFF, (addr >> 8) & 0xFF, (addr >> 16) & 0xFF, (addr >> 24) & 0xFF);
	}

	private boolean _setStaticIpArgument(String key, String value) {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		if (!isIpAddress(value)) {
			error("Invalid IP address format.");
			return false;
		}
		try {
			Settings.System.putString(mContext.getContentResolver(), key, value);
			return true;
		} catch (Exception e) {
			error(e.getLocalizedMessage());
			return false;
		}
	}
	private String _getStaticIpArgument(String key) {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return "";
		}
		try {
			return System.getString(mContext.getContentResolver(), key);
		} catch (Exception e) {
			error(e.getLocalizedMessage());
			return "";
		}
	}

	public static boolean isIpAddress(String value) {

		int start = 0;
		int end = value.indexOf('.');
		int numBlocks = 0;

		while (start < value.length()) {

			if (end == -1) {
				end = value.length();
			}

			try {
				int block = Integer.parseInt(value.substring(start, end));
				if ((block > 255) || (block < 0)) { return false; }
			} catch (NumberFormatException e) {
				return false;
			}

			numBlocks++;

			start = end + 1;
			end = value.indexOf('.', start);
		}

		return numBlocks == 4;
	}

	private final Context mContext;
	private final Browser mBrowser;
	private boolean mIsListeningToBroadcast = false;

	public RexseeWiFi(Context context) {
		super();
		mBrowser = null;
		mContext = context;
	}
	public RexseeWiFi(Browser browser) {
		super();
		mBrowser = browser;
		mContext = browser.getContext();
		mBrowser.eventList.add(EVENT_ONSTATECHANGED);
		mBrowser.eventList.add(EVENT_ONNETWORKCHANGED);
		mBrowser.eventList.add(EVENT_ONNETWORKIDSCHANGED);
		mBrowser.eventList.add(EVENT_ONRSSICHANGED);
		mBrowser.eventList.add(EVENT_ONSCANFINISHED);
		mBrowser.eventList.add(EVENT_ONSUPPLICANTCONNECTIONCHANGED);
		mBrowser.eventList.add(EVENT_ONSUPPLICANTSTATECHANGED);
	}

	//Basic

	public boolean isEnabled() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		return wifi.isWifiEnabled();
	}
	public String getState() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		return _getWiFiState(wifi.getWifiState());
	}
	public boolean enable() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		return wifi.setWifiEnabled(true);
	}
	public boolean disable() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		return wifi.setWifiEnabled(false);
	}
	public String getMacAddress() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return "";
		}
		WifiInfo info = wifi.getConnectionInfo();
		return info.getMacAddress();
	}
	public void openSettings() {
		Intent intent = new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK);
		mContext.startActivity(intent);
	}

	//Sleep
	public String getSleepPolicy() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return "";
		}
		int value = Settings.System.getInt(mContext.getContentResolver(),
				Settings.System.WIFI_SLEEP_POLICY, Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
		switch (value) {
			case Settings.System.WIFI_SLEEP_POLICY_NEVER :
				return "NEVER";
			case Settings.System.WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED :
				return "NEVER_WHILE_PLUGGED";
			default :
				return "DEFAULT";
		}
	}
	public boolean setSleepPolicy(String policy) {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		int value;
		if (policy.equalsIgnoreCase("NEVER")) value = Settings.System.WIFI_SLEEP_POLICY_NEVER;
		else if (policy.equalsIgnoreCase("NEVER_WHILE_PLUGGED")) value = Settings.System.WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED;
		else value = Settings.System.WIFI_SLEEP_POLICY_DEFAULT;
		try {
			Settings.System.putInt(mContext.getContentResolver(), Settings.System.WIFI_SLEEP_POLICY, value);
			return true;
		} catch (Exception e) {
			error(e.getLocalizedMessage());
			return false;
		}
	}

	//Static IP
	public boolean isStaticIp() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		return System.getInt(mContext.getContentResolver(), System.WIFI_USE_STATIC_IP, 0) != 0;
	}
	public boolean enableStaticIp() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		try {
			Settings.System.putInt(mContext.getContentResolver(), Settings.System.WIFI_USE_STATIC_IP, 1);
			return true;
		} catch (Exception e) {
			error(e.getLocalizedMessage());
			return false;
		}
	}
	public boolean disableStaticIp() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		try {
			Settings.System.putInt(mContext.getContentResolver(), Settings.System.WIFI_USE_STATIC_IP, 0);
			return true;
		} catch (Exception e) {
			error(e.getLocalizedMessage());
			return false;
		}
	}

	public String getStaticIp() {
		return _getStaticIpArgument(System.WIFI_STATIC_IP);
	}
	public boolean setStaticIp(String ip) {
		return _setStaticIpArgument(System.WIFI_STATIC_IP, ip);
	}
	public String getStaticGateway() {
		return _getStaticIpArgument(System.WIFI_STATIC_GATEWAY);
	}
	public boolean setStaticGateway(String ip) {
		return _setStaticIpArgument(System.WIFI_STATIC_GATEWAY, ip);
	}
	public String getStaticNetmask() {
		return _getStaticIpArgument(System.WIFI_STATIC_NETMASK);
	}
	public boolean setStaticNetmask(String ip) {
		return _setStaticIpArgument(System.WIFI_STATIC_NETMASK, ip);
	}
	public String getStaticDNS1() {
		return _getStaticIpArgument(System.WIFI_STATIC_DNS1);
	}
	public boolean setStaticDNS1(String ip) {
		return _setStaticIpArgument(System.WIFI_STATIC_DNS1, ip);
	}
	public String getStaticDNS2() {
		return _getStaticIpArgument(System.WIFI_STATIC_DNS2);
	}
	public boolean setStaticDNS2(String ip) {
		return _setStaticIpArgument(System.WIFI_STATIC_DNS2, ip);
	}

	//Supplicant
	public boolean pingSupplicant() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		return wifi.pingSupplicant();
	}
	public String getSupplicantState() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return "";
		}
		WifiInfo info = wifi.getConnectionInfo();
		return _getSupplicantState(info.getSupplicantState());
	}

	//Configured networks
	public String getRememberedNetworks() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return "[]";
		}
		List<WifiConfiguration> list = wifi.getConfiguredNetworks();
		List<ScanResult> results = wifi.getScanResults();
		String rtn = "";
		for (int i = 0; i < list.size(); i++) {
			if (i != 0) rtn += ",";
			rtn += _getConfiguredNetwork(results, list.get(i));
		}
		return "[" + rtn + "]";
	}

	public int remember(String SSID, String security, String password) {
		return remember(null, SSID, security, password);
	}
	public int remember(String BSSID, String SSID, String security, String password) {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return -1;
		}
		if (SSID == null || SSID.equals("")) {
			mBrowser.exception(getInterfaceName(), "SSID could not be null or blank.");
			return -1;
		}
		WifiConfiguration config = new WifiConfiguration();
		if (BSSID != null && !BSSID.equals("")) config.BSSID = BSSID;
		config.SSID = _convertToQuotedString(SSID);
		if (security.equalsIgnoreCase(SECURITY_NONE)) {
			config.allowedKeyManagement.set(KeyMgmt.NONE);
		} else if (security.equalsIgnoreCase(SECURITY_WEP)) {
			config.allowedKeyManagement.set(KeyMgmt.NONE);
			config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
			config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
			if (password.length() != 0) {
				int length = password.length();
				// WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
				if ((length == 10 || length == 26 || length == 58) && password.matches("[0-9A-Fa-f]*")) {
					config.wepKeys[0] = password;
				} else {
					config.wepKeys[0] = '"' + password + '"';
				}
			}
		} else if (security.equalsIgnoreCase(SECURITY_PSK)) {
			config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
			if (password.length() != 0) {
				if (password.matches("[0-9A-Fa-f]{64}")) {
					config.preSharedKey = password;
				} else {
					config.preSharedKey = '"' + password + '"';
				}
			}
		} else if (security.equalsIgnoreCase(SECURITY_EAP)) {
			/*
			config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
			config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
			config.eap.setValue((String) mEapMethod.getSelectedItem());

			config.phase2.setValue((mPhase2.getSelectedItemPosition() == 0) ? "" : 
					"auth=" + mPhase2.getSelectedItem());
			config.ca_cert.setValue((mEapCaCert.getSelectedItemPosition() == 0) ? "" :
					KEYSTORE_SPACE + Credentials.CA_CERTIFICATE +
							(String) mEapCaCert.getSelectedItem());
			config.client_cert.setValue((mEapUserCert.getSelectedItemPosition() == 0) ? "" :
					KEYSTORE_SPACE + Credentials.USER_CERTIFICATE +
							(String) mEapUserCert.getSelectedItem());
			config.private_key.setValue((mEapUserCert.getSelectedItemPosition() == 0) ? "" :
					KEYSTORE_SPACE + Credentials.USER_PRIVATE_KEY +
							(String) mEapUserCert.getSelectedItem());
			config.identity.setValue((mEapIdentity.length() == 0) ? "" :
					mEapIdentity.getText().toString());
			config.anonymous_identity.setValue((mEapAnonymous.length() == 0) ? "" :
					mEapAnonymous.getText().toString());
			if (password.length() != 0) {
				config.password.setValue(password);
			}
			*/
			mBrowser.exception(getInterfaceName(), "WiFi with EAP security is not supported to add manually.");
			return -1;
		} else {
			mBrowser.exception(getInterfaceName(), "Invalid security setup.");
			return -1;
		}
		int networkId = wifi.addNetwork(config);
		wifi.saveConfiguration();
		wifi.enableNetwork(networkId, false);
		return networkId;
	}
	public boolean forget(int networkId) {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		wifi.removeNetwork(networkId);
		return true;
	}

	public void connect(int networkId) {

		if (networkId < 0) return;
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return;
		}

		//Set all priorities to zero
		List<WifiConfiguration> list = wifi.getConfiguredNetworks();
		for (int i = list.size() - 1; i >= 0; --i) {
			WifiConfiguration config = list.get(i);
			if (config != null) {
				WifiConfiguration newConfig = new WifiConfiguration();
				newConfig.networkId = config.networkId;
				newConfig.priority = 0;
				wifi.updateNetwork(newConfig);
			}
		}

		// Set to the highest priority and save the configuration.
		WifiConfiguration config = new WifiConfiguration();
		config.networkId = networkId;
		config.priority = 1000000;
		wifi.updateNetwork(config);
		wifi.saveConfiguration();

		// Connect to network by disabling others.
		wifi.enableNetwork(networkId, true);
		wifi.reconnect();
		//enableNetworks();

	}

	public boolean enableNetwork(int networkId) {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		return wifi.enableNetwork(networkId, false);
	}
	public boolean enableNetworks() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		List<WifiConfiguration> list = wifi.getConfiguredNetworks();
		for (int i = list.size() - 1; i >= 0; --i) {
			WifiConfiguration config = list.get(i);
			if (config != null && config.status != Status.ENABLED) {
				wifi.enableNetwork(config.networkId, false);
			}
		}
		return wifi.saveConfiguration();
	}
	public boolean disableNetwork(int networkId) {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		return wifi.disableNetwork(networkId);
	}
	public boolean disableNetworks() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		List<WifiConfiguration> list = wifi.getConfiguredNetworks();
		for (int i = list.size() - 1; i >= 0; --i) {
			WifiConfiguration config = list.get(i);
			if (config != null && config.status != Status.DISABLED) {
				wifi.disableNetwork(config.networkId);
			}
		}
		return wifi.saveConfiguration();
	}

	//Scan
	public boolean scan() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		wifi.startScan();
		return true;
	}
	public String getScanResults() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return "[]";
		}
		List<WifiConfiguration> configs = wifi.getConfiguredNetworks();
		List<ScanResult> list = wifi.getScanResults();
		String rtn = "";
		for (int i = 0; i < list.size(); i++) {
			if (i != 0) rtn += ",";
			rtn += _getScanResult(list.get(i), configs);
		}
		return "[" + rtn + "]";
	}

	//WiFi lock
	public boolean createMulticastLock() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		return true;
	}
	public boolean createWifiLock() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		return true;
	}

	//Broadcast Listener	
	public boolean isListeningToBroascast() {
		return mIsListeningToBroadcast;
	}
	public boolean startListenerForBroadcast() {

		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}

		if (mIsListeningToBroadcast) return true;

		mContext.registerReceiver(EVENT_ONSTATECHANGED_Receiver, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
		mContext.registerReceiver(EVENT_ONNETWORKCHANGED_Receiver, new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION));
		mContext.registerReceiver(EVENT_ONNETWORKIDSCHANGED_Receiver, new IntentFilter(WifiManager.NETWORK_IDS_CHANGED_ACTION));
		mContext.registerReceiver(EVENT_ONRSSICHANGED_Receiver, new IntentFilter(WifiManager.RSSI_CHANGED_ACTION));
		mContext.registerReceiver(EVENT_ONSCANFINISHED_Receiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
		mContext.registerReceiver(EVENT_ONSUPPLICANTCONNECTIONCHANGED_Receiver, new IntentFilter(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION));
		mContext.registerReceiver(EVENT_ONSUPPLICANTSTATECHANGED_Receiver, new IntentFilter(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION));

		mIsListeningToBroadcast = true;

		return true;

	}
	public boolean stopListenerForBroadcast() {

		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}

		if (!mIsListeningToBroadcast) return true;

		mContext.unregisterReceiver(EVENT_ONSTATECHANGED_Receiver);
		mContext.unregisterReceiver(EVENT_ONNETWORKCHANGED_Receiver);
		mContext.unregisterReceiver(EVENT_ONNETWORKIDSCHANGED_Receiver);
		mContext.unregisterReceiver(EVENT_ONRSSICHANGED_Receiver);
		mContext.unregisterReceiver(EVENT_ONSCANFINISHED_Receiver);
		mContext.unregisterReceiver(EVENT_ONSUPPLICANTCONNECTIONCHANGED_Receiver);
		mContext.unregisterReceiver(EVENT_ONSUPPLICANTSTATECHANGED_Receiver);

		mIsListeningToBroadcast = false;

		return true;

	}

	//Current networks
	public int getNetowrkId() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return -1;
		}
		WifiInfo info = wifi.getConnectionInfo();
		return info.getNetworkId();
	}
	public String getBSSID() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return "";
		}
		WifiInfo info = wifi.getConnectionInfo();
		return info.getBSSID();
	}
	public String getSSID() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return "";
		}
		WifiInfo info = wifi.getConnectionInfo();
		return info.getSSID();
	}
	public String getIpAddress() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return "-1";
		}
		WifiInfo info = wifi.getConnectionInfo();
		return _getIpAddress(info.getIpAddress());
	}
	public int getRssi() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return -1;
		}
		WifiInfo info = wifi.getConnectionInfo();
		return info.getRssi();
	}
	public int getLinkSpeed() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return -1;
		}
		WifiInfo info = wifi.getConnectionInfo();
		return info.getLinkSpeed();
	}
	public String getDHCPInfo() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return "";
		}
		DhcpInfo dhcp = wifi.getDhcpInfo();
		String rtn = "{";
		rtn += "\"dns1\":\"" + _getIpAddress(dhcp.dns1) + "\"";
		rtn += ",\"dns2\":\"" + _getIpAddress(dhcp.dns2) + "\"";
		rtn += ",\"gateway\":\"" + _getIpAddress(dhcp.gateway) + "\"";
		rtn += ",\"ip\":\"" + _getIpAddress(dhcp.ipAddress) + "\"";
		rtn += ",\"leaseDuration\":" + dhcp.leaseDuration;
		rtn += ",\"netmask\":\"" + _getIpAddress(dhcp.netmask) + "\"";
		rtn += ",\"serverAddress\":\"" + _getIpAddress(dhcp.serverAddress) + "\"";
		rtn += "}";
		return rtn;
	}
	public boolean reconnect() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		wifi.reassociate();
		return true;
	}
	public boolean disconnect() {
		WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
		if (!wifi.isWifiEnabled()) {
			error(EXCEPTION_NOT_ENABLED);
			return false;
		}
		wifi.disconnect();
		return true;
	}

}
